package com.hy.mvc.biz.excel.exportstrategy;

import com.google.common.collect.Lists;
import com.hy.mvc.biz.excel.anotation.CellDataTransform;
import com.hy.mvc.biz.excel.convert.ICellDataTransformer;
import com.hy.mvc.biz.excel.model.SimpleExcelModel;
import com.hy.mvc.biz.utils.ReflectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ss.usermodel.CellStyle;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by Booker on 2017/7/3.
 */
@Component("simpleContentStrategy")
public class SimpleContentStrategy implements ContentStrategy {
    private static Log log = LogFactory.getLog(SimpleContentStrategy.class);

    private static final int START_ROW_INDEX = 3;

    @Override
    public HSSFSheet buildContent(HSSFSheet workSheet, SimpleExcelModel excelModel, List<?> exportList) {
        if (exportList != null && exportList.size() > 0) {
            Object[] row = new Object[]{};

            HSSFCellStyle bodyCellStyle = workSheet.getWorkbook().createCellStyle();

            for (int i = 0; i < exportList.size(); i++) {
                List<Object> rowList = Lists.newLinkedList();

                if (excelModel.getExportFields() == null
                        || excelModel.getExportFields().length == 0) {
                    throw new IllegalStateException(excelModel.getFileName()
                            + "EXCEL文件导出字段列表为空,请检查相关配置!");
                }

                for (String fieldName : excelModel.getExportFields()) {
                    if (StringUtils.isBlank(fieldName)) {
                        log.info("fieldName:" + fieldName);
                        throw new IllegalStateException(excelModel.getFileName() + "EXCEL文件导出字段列表为空,请检查相关配置!");
                    }

                    Object exportObj = exportList.get(i);
                    Field field = null;
                    Object exportVal = null;

                    if (exportObj instanceof Map) {     //如果是map，则按key取值
                        Map<String, Object> rowMap = (Map<String, Object>) exportObj;
                        exportVal = rowMap.get(fieldName);
                    } else {
                        for (String splitfieldName : StringUtils.split(fieldName, ".")) {
                            exportObj = getExportValue(i, splitfieldName, exportObj, field, exportVal);
                        }
                        exportVal = exportObj;
                    }


                    rowList.add(exportVal);
                }
                workSheet = buildRow(workSheet, bodyCellStyle, workSheet.getLastRowNum() + 1, rowList.toArray(row));
            }
        }
        return workSheet;
    }

    private HSSFSheet buildRow(HSSFSheet workSheet, HSSFCellStyle bodyCellStyle, int startRowIndex, Object... objects) {
        bodyCellStyle.setAlignment(CellStyle.ALIGN_CENTER);
        bodyCellStyle.setWrapText(false);

        int startColIndex = 0;
        HSSFRow row = workSheet.createRow(startRowIndex);
        for (int i = 0; i < objects.length; i++) {
            HSSFCell cell = row.createCell((short) startColIndex + i);
            if (objects[i] == null) {
                cell.setCellValue(StringUtils.EMPTY);
            } else if (objects[i] instanceof Date) {
                cell.setCellValue((Date) objects[i]);
            } else if (objects[i] instanceof Calendar) {
                cell.setCellValue((Calendar) objects[i]);
            } else if (objects[i].getClass().isPrimitive() || objects[i] instanceof Number) {
                cell.setCellValue(NumberUtils.createNumber(String.valueOf(objects[i])).doubleValue());
            } else if (objects[i] instanceof Boolean) {
                cell.setCellValue(Boolean.parseBoolean(objects[i].toString()));
            } else {
                cell.setCellValue(objects[i].toString());
            }
            cell.setCellStyle(bodyCellStyle);
        }

        return workSheet;
    }

    private Object getExportValue(int i, String fieldName, Object exportObj, Field field, Object exportVal) {
        if (exportObj == null) {
            return exportVal;
        }

        try {
            field = ReflectionUtils.getAccessibleField(exportObj, fieldName);

            if (field != null) {
                exportVal = field.get(exportObj);

                for (Annotation annotation : field.getDeclaredAnnotations()) {
                    if (annotation.annotationType().isAnnotationPresent(CellDataTransform.class)) {
                        CellDataTransform cellDataTransform = annotation.annotationType().getAnnotation(CellDataTransform.class);
                        ICellDataTransformer cellDataTransformer = ReflectionUtils.clazzInitialize(cellDataTransform.value());
                        if (cellDataTransformer != null) {
                            exportVal = cellDataTransformer.convert(field, exportObj);
                        }
                        break;
                    }
                }
            }
        } catch (Exception e) {
            if (log.isErrorEnabled()) {
                log.error("在导出Excel的过程中,由导出字段:" + fieldName + "(位于导出列表的第" + i
                        + 1 + "个位置)的属性名反射得到属性值时出错!", e);
            }
        } finally {
            if (field != null) {
                field.setAccessible(Boolean.FALSE);
            }
        }
        return exportVal;
    }

    @Override
    public int getStartRowIndex() {
        return START_ROW_INDEX;
    }
}
